import { defineStore } from "pinia";
import { ref } from "vue";
import { refresh } from "@/api/auth";
import { Token } from "@/types";

const KEY = "token";

/**
 * 令牌信息
 */
export const useTokenStore = defineStore(KEY, () => {
  const notificationLogin = ref(false);
  const currentToken = ref(
    sessionStorage.getItem(KEY) ? `Bearer ${sessionStorage.getItem(KEY)}` : ""
  );

  function set(token: Token) {
    if (token.accessToken) {
      sessionStorage.setItem(KEY, token.accessToken);
    }
    if (currentToken.value) {
      localStorage.setItem(
        KEY,
        JSON.stringify({
          expire: new Date().getTime() + token.expire,
          refreshToken: token.refreshToken,
        })
      );
    }
    currentToken.value = `Bearer ${token.accessToken}`;
  }

  function get() {
    return currentToken.value;
  }

  function getRefreshToken() {
    if (!isExpired()) {
      const { refreshToken } = localStorage.getItem(KEY)
        ? JSON.parse(localStorage.getItem(KEY)!)
        : {};
      return refreshToken;
    }
    return "";
  }

  function clear() {
    localStorage.removeItem(KEY);
    sessionStorage.removeItem(KEY);
    currentToken.value = "";
  }

  function isLogin() {
    return getRefreshToken();
  }

  function isExpired() {
    if (localStorage.getItem(KEY)) {
      const { expire } = localStorage.getItem(KEY)
        ? JSON.parse(localStorage.getItem(KEY)!)
        : {};
      if (new Date().getTime() < expire) {
        return false;
      }
    }
    return true;
  }

  /**
   * 通知登录
   */
  function notifyToLogin() {
    notificationLogin.value = true;
  }

  /**
   * 监听通知
   * @returns
   */
  function notification() {
    return notificationLogin.value;
  }

  /**
   * 接受登录通知
   */
  function receive() {
    notificationLogin.value = false;
  }

  /**
   * 刷新token
   */
  async function refreshToken() {
    const token = getRefreshToken();
    const { data } = await refresh({ refreshToken: token });
    if (data) {
      const { expire } = JSON.parse(localStorage.getItem(KEY)!);
      set({ accessToken: data, expire: expire, refreshToken: token });
      return true;
    } else {
      // 刷新失败则通知登录
      notifyToLogin();
      return false;
    }
  }

  return {
    set,
    get,
    clear,
    isLogin,
    isExpired,
    getRefreshToken,
    notifyToLogin,
    notification,
    receive,
    refreshToken,
  };
});
